﻿using CustomCharacter;
using CustomCharacter.Ability;
using CustomPlayerEffects;
using Exiled.API.Enums;
using Exiled.API.Features;
using Exiled.Events.EventArgs.Interfaces;
using Exiled.Events.EventArgs.Player;
using InventorySystem;
using InventorySystem.Items.Firearms;
using InventorySystem.Items.Firearms.Attachments;
using MEC;
using PlayerRoles;
using PlayerStatsSystem;
using RgCore.Events;
using RgCore.Misc;
using RgCore.PlayerHud;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using CustomCharacter.Interfaces;
using RgCore.CustomSide;
using UnityEngine;
using VoiceChat;

namespace Scp035
{
    [RoleInfo("SCP-035", Side.Scp, PlayerRoles.RoleTypeId.ClassD, PlayerRoles.RoleTypeId.ClassD, MaxHealth = 400)]
    public class Scp035 : CustomCharacter.CustomCharacter,
        IScpNumber, ICustomSpawnpoint, IRoundStartSpawn, ITrialCard, IVoiceChannelModifcation
    {
        public Scp035(int id) : base(id)
        {
        }

        public override Color32 RoleColor => new Color32(255, 0, 0, 255);

        public Vector3 SpawnPosition => Exiled.API.Extensions.RoleExtensions.GetRandomSpawnLocation(PlayerRoles.RoleTypeId.Scp939).Position;

        public string ScpNumber => "035";

        [Description("剩余附身")]
        public int RemainingTimes
        {
            get
            {
                if (AbilityManager.Abilities.TryGetValue(Player, out var ability))
                {
                    var index = ability.FindIndex(x => x.Ability.AbilityId == "Scp035_Attr_1");
                    if (index >= 0)
                    {
                        return (int)ability[index].Datas["times"];
                    }
                }
                return 0;
            }
        }

        public byte MinPlayers => 20;

        public int Cost => 300;

        public VoiceChatChannel[] AvailableVoiceChannels => new VoiceChatChannel[] { VoiceChatChannel.ScpChat };

        public bool PrimaryModification => true;

        public override IEnumerable<Ability> AbilityRegister()
        {
            return new Ability[]
            {
                new AttributeAbility("Scp035_Attr_1",
    "死亡后，若8m范围内有任何非插件角色的敌方玩家，则将会选择最近的玩家进行附身，并立即使被附身者掉落所有物品。" +
    "附身期间，被附身玩家无法移动。附身最多2次。每秒钟有0.5的血量衰减", Attribute_1,true,
    new IExiledEvent[] { EventProcessor.OnDying },
    new KeyValuePair<string, object>[]{
        new KeyValuePair<string, object>("times", 2),
        new KeyValuePair<string, object>("occuping", false)
    }, GetType())
              };
        }

        public override void Role_Activate()
        {
            base.Role_Activate();
            Firearm firearm = (Firearm)Player.Inventory.ServerAddItem(ItemType.GunCOM18);
            if (AttachmentsServerHandler.PlayerPreferences.TryGetValue(Player.ReferenceHub, out Dictionary<ItemType, uint> dictionary) && dictionary.TryGetValue(firearm.ItemTypeId, out uint code))
            {
                firearm.ApplyAttachmentsCode(code, true);
            }
            FirearmStatusFlags firearmStatusFlags = FirearmStatusFlags.MagazineInserted;
            if (firearm.HasAdvantageFlag(AttachmentDescriptiveAdvantages.Flashlight))
            {
                firearmStatusFlags |= FirearmStatusFlags.FlashlightEnabled;
            }
            firearm.Status = new FirearmStatus(firearm.AmmoManagerModule.MaxAmmo, firearmStatusFlags, firearm.GetCurrentAttachmentsCode());
        }

        private static AbilityOutput Attribute_1(Player player, ref AbilityInfo info, IExiledEvent e, AbilityTrigger trigger)
        {
            var data = info.Datas;
            var occuping = (bool)data["occuping"];
            int times = (int)data["times"];
            if (trigger == AbilityTrigger.Update)
            {
                if (!occuping)
                    player.ReferenceHub.playerStats.DealDamage(new CustomReasonDamageHandler("被面具腐蚀而死", 0.5f));
                return new AbilityOutput(true);
            }
            else if (trigger != AbilityTrigger.Event)
            {
                return new AbilityOutput(false);
            }
            if (e is DyingEventArgs ev && ev.Player == player)
            {
                if (times <= 0 || occuping)
                {
                    return new AbilityOutput(true);
                }
                Dictionary<Player, float> avaPlayers = new Dictionary<Player, float>();
                foreach (Player ply in Player.List)
                {
                    if (Vector3.Distance(ev.Player.Position, ply.Position) <= 15f && ply != player && !player.IsFriendly(ply))
                        avaPlayers.Add(ply, Vector3.Distance(ev.Player.Position, ply.Position));
                }
                if (avaPlayers.Count == 0)
                {
                    ev.Player.SendFormattedMsg("", "<color=#FF0000>SCP-035</color>", "附近无可附身对象，你的面具被永远留在这里。。", 3,
                        MsgType.Message, ScreenLocation.CenterTop, true);
                    return new AbilityOutput(true);
                }
                ev.IsAllowed = false;
                data["occuping"] = true;
                ev.Player.Heal(50f);
                Player ply1 = avaPlayers.Where(p => p.Value == avaPlayers.Values.Min()).First().Key;
                ply1.DropItems();
                Vector3 position = ply1.Position;
                RoleTypeId role = ply1.Role;
                ply1.EnableEffect<Ensnared>(1, 2);
                ply1.SendRawMsg("", "<color=red><b>我渴望它...现在它是我的了..</b></color>", 5, ScreenLocation.CenterBottom, true);
                data["times"] = (int)data["times"] - 1;
                Timing.CallDelayed(2f, () =>
                {
                    try
                    {
                        if (!ev.Player.IsAlive)
                        {
                            return;
                        }
                        ev.Player.Role.Set(role, SpawnReason.ForceClass, RoleSpawnFlags.None);
                        var inst = ev.Player.GetCharacterInstance();
                        if (inst != null)
                        {
                            ev.Player.MaxHealth = inst.Attribute.MaxHealth;
                        }
                        ev.Player.Health = ev.Player.MaxHealth;
                        ply1.ReferenceHub.playerStats.KillPlayer(new CustomReasonDamageHandler("被附身而死"));
                        data["occuping"] = false;
                        ev.Player.Position = position;
                        ev.Player.AddScore(200, "附身玩家");
                    }
                    catch (Exception ex)
                    {
                        Log.Error(ex);
                    }
                });
            }
            return new AbilityOutput(false);
        }
    }
}